﻿/*
 *
 * FilePath     : singleton.h
 * Version      : 1.2
 * Description  : 单例宏
 * 				1. 使用QSharedPointer管理单例对象
 * 				2. 线程安全
 * 				3. 允许在子线程中手动创建
 *
 * Author       : 岳凯(1585202329@qq.com)
 * Date         : 2024-12-27 14:45:28
 *
 * LastEditors  : 岳凯(1585202329@qq.com)
 * LastEditTime : 2024-12-27 15:42:54
 *
 * Example      :
 * class YourClass : public QObject {
 *     Q_OBJECT
 *     SINGLETONG(YourClass)
 *     // ...
 * };
 *
 * • getInstance() 是原有的“懒汉式”接口：若没有实例就直接在当前线程创建。
• createInstance() 是新增接口：允许外部在指定线程中手动构造对象(或先 new T，再 moveToThread)。
 */

#pragma once
#ifndef SINGLETON_H
#define SINGLETON_H

#include <QMutex>
#include <QScopedPointer>
#include <QSharedPointer>
#include <mutex>
template <typename T>
class Singleton {
public:
	// 获取单例实例
	static QSharedPointer<T> getInstance();
	// 查询是否已有实例
	static bool hasInstance() {
		return !instance.isNull();
	}
	// 禁止拷贝/赋值
	Singleton(const Singleton&) = delete;
	Singleton<T>& operator=(const Singleton&) = delete;

	// 手动创建，并将对象设为单例(典型场景：在子线程中延迟构造)
	// 若已存在实例，则返回已有实例(不会重复创建)
	static QSharedPointer<T> createInstance() {
		std::lock_guard<std::mutex> locker(mutex);
		if (instance.isNull()) {
			// 直接 new T()，可由调用者自行moveToThread
			instance.reset(new T);
		}
		return instance;
	}


protected:
	// 允许子类重写构造/析构
	Singleton() = default;
	virtual ~Singleton() = default;

private:
	// 用于多线程安全的锁
	static std::mutex mutex;
	// 保存单例的实例
	static QSharedPointer<T> instance;
};

// --- 以下为模板成员的定义，需放在头文件中 ---

template <typename T>
std::mutex Singleton<T>::mutex;

template <typename T>
QSharedPointer<T> Singleton<T>::instance;

template <typename T>
QSharedPointer<T> Singleton<T>::getInstance() {
	if (instance.isNull()) {
		std::lock_guard<std::mutex> locker(mutex);
		if (instance.isNull()) {
			// 使用QSharedPointer创建单例，必要时可自定义deleter
			instance.reset(new T); // 主动在当前线程创建
		}
	}
	return instance;
}

// 宏封装，便于在具体类中使用
#define SINGLETON(Class) \
private: \
    friend class Singleton<Class>; \
public:  \
    static QSharedPointer<Class> getInstance() { \
        return Singleton<Class>::getInstance();  \
    } \
    static QSharedPointer<Class> createInstance() { \
        return Singleton<Class>::createInstance(); \
    }                                          \
	static bool hasInstance() {    				\
	return Singleton<Class>::hasInstance();		\
	}

#endif // SINGLETON_H